home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
source
/
vr386
/
miscmath.asm
< prev
next >
Wrap
Assembly Source File
|
1994-01-10
|
10KB
|
571 lines
TITLE MISCMATH - VARIOUS MATH IN ASSEMBLER
COMMENT $
// Routines to do various math that can't be done in C.
// Some are just for efficiency, and could be done in C with
// a true 32-bit compiler. Others use 64-bit intermediate results.
// All code by Dave Stampe, last updated 23/12/93
/*
This code is part of the VR-386 project, created by Dave Stampe.
VR-386 is a desendent of REND386, created by Dave Stampe and
Bernie Roehl. Almost all the code has been rewritten by Dave
Stampre for VR-386.
Copyright (c) 1994 by Dave Stampe:
May be freely used to write software for release into the public domain
or for educational use; all commercial endeavours MUST contact Dave Stampe
(dstampe@psych.toronto.edu) for permission to incorporate any part of
this software or source code into their products! Usually there is no
charge for under 50-100 items for low-cost or shareware products, and terms
are reasonable. Any royalties are used for development, so equipment is
often acceptable payment.
ATTRIBUTION: If you use any part of this source code or the libraries
in your projects, you must give attribution to VR-386 and Dave Stampe,
and any other authors in your documentation, source code, and at startup
of your program. Let's keep the freeware ball rolling!
DEVELOPMENT: VR-386 is a effort to develop the process started by
REND386, improving programmer access by rewriting the code and supplying
a standard API. If you write improvements, add new functions rather
than rewriting current functions. This will make it possible to
include you improved code in the next API release. YOU can help advance
VR-386. Comments on the API are welcome.
CONTACT: dstampe@psych.toronto.edu
*/
$
.MODEL large
; # define XFSC 536870912 /* 2**29 for shifting xform coeffs to long */
.DATA
_longmath_overflow dd 0 ;; overflow/high dword return
.CODE INTMATH
MULT29 MACRO a,b ; multiply <3.29> -> eax
mov eax,DWORD PTR a
imul DWORD PTR b
shrd eax,edx,29
adc eax,0
ENDM
MMULT29 MACRO a,b,c ; multiply 3 of <3.29> -> eax
mov eax,DWORD PTR a
imul DWORD PTR b
shrd eax,edx,29
adc eax,0
imul DWORD PTR c
shrd eax,edx,29
adc eax,0
ENDM
DOTPROD MACRO a,b,c,x,y,z,p ; dot product plus p, accum in ecx:ebx
mov eax,a ; result in eax
imul DWORD PTR x
mov ecx,edx
mov ebx,eax
mov eax,b
imul DWORD PTR y
add ebx,eax
adc ecx,edx
mov eax,c
imul DWORD PTR z
add eax,ebx
adc edx,ecx
shrd eax,edx,29
adc eax,p
ENDM
;/****************** MISC. MATH SUPPORT **********/
;long m_mult(long a, long b) /* perform mult. by matrix element */
;{ /* where either a or b is in <3.29> format */
a equ [bp+8] ; arguments
b equ [bp+12]
PUBLIC _m_mult
_m_mult proc far
.386
push ebp
mov ebp,esp
MULT29 a,b
shld edx,eax,16 ; return in dx:ax
mov esp,ebp
pop ebp
ret
_m_mult endp
;long m2_mult(long a, long b, long c) /* perform mult. by matrix element */
;{ /* where a and b is in <3.29> format */
a equ [bp+8] ; arguments
b equ [bp+12]
b equ [bp+16]
PUBLIC _m_mult
_m2_mult proc far
.386
push ebp
mov ebp,esp
MMULT29 a,b,c
shld edx,eax,16 ; return in dx:ax
mov esp,ebp
pop ebp
ret
_m2_mult endp
;long divide_29(long a, long b) /* perform divide, result in <3.29> format */
;{ /* up to user to test for overflow */
a equ DWORD PTR [bp+8] ; arguments
b equ DWORD PTR [bp+12]
PUBLIC _divide_29
_divide_29 proc far
.386
push ebp
mov ebp,esp
mov eax,a
cdq
shld edx,eax,29
shl eax,29
idiv b
shld edx,eax,16 ; return in dx:ax
mov esp,ebp
pop ebp
ret
_divide_29 endp
;long divide_long(long ahi, long alo, long b)
a equ DWORD PTR [bp+8] ; arguments
b equ DWORD PTR [bp+12]
b equ DWORD PTR [bp+16]
PUBLIC _divide_long
_divide_long proc far
.386
push ebp
mov ebp,esp
mov eax,alo
mov edx,ahi
idiv b
mov _longmath_overflow,edx
shld edx,eax,16 ; return in dx:ax
mov esp,ebp
pop ebp
ret
_divide_long endp
;long mult_long(long a, long b) /* perform multiply on longs */
a equ DWORD PTR [bp+8] ; arguments
b equ DWORD PTR [bp+12]
PUBLIC _mult_long
_mult_long proc far
.386
push ebp
mov ebp,esp
mov eax,a
imul b
mov _longmath_overflow,edx
shld edx,eax,16 ; return in dx:ax
mov esp,ebp
pop ebp
ret
_mult_long endp
; // shifts 32-bit signed number left or right (>0 is left, <0 is right)
;extern long_shift32(long a, int shift);
a equ DWORD PTR [bp+8] ; arguments
shift equ WORD PTR [bp+12]
PUBLIC _long_shift32
_long_shift32 proc far
.386
push ebp
mov ebp,esp
mov eax,a
cdq
mov cx,shift
or cx,cx
jge left_shift32
neg cx
shrd eax,edx,cl
shr edx,cl
adc eax,0
adc edx,0
mov _longmath_overflow,edx
jmp done_shift32
left_shift32:
shld edx,eax,cl
shl eax,cl
mov _longmath_overflow,edx
done_shift32:
shld edx,eax,16 ; return in dx:ax and eax
mov esp,ebp
pop ebp
ret
_long_shift32 endp
; // shifts 64-bit signed number left or right (>0 is left, <0 is right)
; // msdword of result is returned in longmath_overflow
;extern long_shift64(long ahi, long alo, int shift);
ahi equ DWORD PTR [bp+8] ; arguments
alo equ DWORD PTR [bp+12]
shift equ WORD PTR [bp+16]
PUBLIC _long_shift64
_long_shift64 proc far
.386
push ebp
mov ebp,esp
mov edx,ahi
mov eax,alo
mov cx,shift
or cx,cx
jge left_shift64
neg cx
shrd eax,edx,cl
shr edx,cl
adc eax,0
adc edx,0
mov _longmath_overflow,edx
jmp done_shift64
left_shift64:
shld edx,eax,cl
shl eax,cl
mov _longmath_overflow,edx
done_shift64:
shld edx,eax,16 ; return in dx:ax and eax
mov esp,ebp
pop ebp
ret
_long_shift64 endp
;long mulmuldiv(long a, long b) /* perform (a*b)/c with 64-bit intermediate */
;{ /* up to user to test for overflow */
a equ DWORD PTR [bp+8] ; arguments
b equ DWORD PTR [bp+12]
c equ DWORD PTR [bp+16]
PUBLIC _mulmuldiv
_mulmuldiv proc far
.386
push ebp
mov ebp,esp
mov eax,a
imul b
idiv c
mov _longmath_overflow,edx
shld edx,eax,16 ; return in dx:ax
mov esp,ebp
pop ebp
ret
_mulmuldiv endp
;long dot_prod_29(long a, long b, long c, long x, long y, long z)
; /* computes (Ax + By + Cz)>>29 */
a equ [bp+8] ; arguments
b equ [bp+12]
c equ [bp+16]
x equ [bp+20]
y equ [bp+24]
z equ [bp+28]
PUBLIC _dot_prod_29
_dot_prod_29 proc far
.386
push ebp
mov ebp,esp
push esi
push edi
push ecx
DOTPROD a,b,c,x,y,z,0
shld edx,eax,16 ; return dx:ax
pop edi
pop esi
mov esp,ebp
pop ebp
ret
_dot_prod_29 endp
;long scale_16(long s, long a, long x) /* perform scaling by 16.16 number */
s equ [bp+8] ; arguments
a equ [bp+12]
x equ [bp+16]
PUBLIC _scale_16
_scale_16 proc far
.386
push ebp
mov ebp,esp
mov eax,DWORD PTR x
add eax,DWORD PTR a
imul DWORD PTR s
shrd eax,edx,16
adc eax,0
shld edx,eax,16 ; return in eax and dx:ax
mov esp,ebp
pop ebp
ret
_scale_16 endp
;long calc_scale_16(long a, long b, long s) /* compute 16.16 scaling factor */
a equ [bp+8] ; arguments
b equ [bp+12]
s equ [bp+16]
PUBLIC _calc_scale_16
_calc_scale_16 proc far
.386
push ebp
mov ebp,esp
xor eax,eax ; return 0 for divide error
mov ebx,DWORD PTR a
sub ebx,DWORD PTR b
je cdiv
mov eax, DWORD PTR s
cdq
shld edx,eax,17
shl eax,17
idiv ebx
cdiv:
shld edx,eax,16 ; return in eax and dx:ax
mov esp,ebp
pop ebp
ret
_calc_scale_16 endp
;long plane_y(long a, long b, long c, long d, long x, long z)
; /* used to compute floor/ceiling of areas */
a equ [bp+8] ; arguments
b equ [bp+12]
c equ [bp+16]
d equ [bp+20]
x equ [bp+24]
z equ [bp+28]
PUBLIC _plane_y
_plane_y proc far
.386
push ebp
mov ebp,esp
;* computes (Ax + Cz + D)/-B */
push esi
push edi
xor eax,eax
test DWORD PTR b,-1
je divzero
mov eax,a
imul DWORD PTR x
mov esi,eax
mov edi,edx
mov eax,c
imul DWORD PTR z
add esi,eax
adc edi,edx
mov eax,DWORD PTR d
cdq
add eax,esi
adc edx,edi
idiv DWORD PTR b
divzero:
shld edx,eax,16 ; return in eax and dx:ax
pop edi
pop esi
mov esp,ebp
pop ebp
ret
_plane_y endp
;/************* 32 BIT CITY-BLOCK DISTANCE *************/
;/* returns abs(x1-x2) + abs(y1-y2) + abs(z1-z2) */
;long big_dist(long x1, long y1, long z1,
; long x2, long y2, long z2 )
x1 equ [bp+8] ; arguments
y1 equ [bp+12]
z1 equ [bp+16]
x2 equ [bp+20]
y2 equ [bp+24]
z2 equ [bp+28]
PUBLIC _big_dist
_big_dist proc far
.386
push ebp
mov ebp,esp
push ecx
mov eax,x1
sub eax,x2
cdq
xor eax,edx
sub eax,edx
mov ecx,eax
mov eax,y1
sub eax,y2
cdq
xor eax,edx
sub eax,edx
add ecx,eax
mov eax,z1
sub eax,z2
cdq
xor eax,edx
sub eax,edx
add eax,ecx
shld edx,eax,16 ; return in eax and dx:ax
pop ecx
mov esp,ebp
pop ebp
ret
_big_dist endp
end